package com.pzhu.dormitory.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pzhu.dormitory.dao.UserDao;
import com.pzhu.dormitory.dao.UserRoleRelationDao;
import com.pzhu.dormitory.dto.UserDTO;
import com.pzhu.dormitory.entity.RoleEntity;
import com.pzhu.dormitory.entity.UserEntity;
import com.pzhu.dormitory.entity.UserRoleRelationEntity;
import com.pzhu.dormitory.service.RoleService;
import com.pzhu.dormitory.service.UserService;
import com.pzhu.dormitory.utils.PageUtils;
import com.pzhu.dormitory.utils.Query;
import com.pzhu.dormitory.utils.R;
import com.pzhu.dormitory.utils.Rb;
import com.pzhu.dormitory.vo.RoleVo;
import com.pzhu.dormitory.vo.UserRoleVo;
import com.pzhu.dormitory.vo.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;


@Service("userService")
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements UserService {


    private final UserRoleRelationDao userRoleRelationDao;
    private final RoleService roleService;

    public UserServiceImpl(UserRoleRelationDao userRoleRelationDao, RoleService roleService) {
        this.userRoleRelationDao = userRoleRelationDao;
        this.roleService = roleService;
    }

    @Override
    public PageUtils<UserEntity> queryPage(Map<String, Object> params) {
        LambdaQueryWrapper<UserEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        String username = (String) params.get("username");
        String status = (String) params.get("status");
        if (StringUtils.isNotBlank(username)) {
            lambdaQueryWrapper.like(UserEntity::getUsername, "%" + username + "%");
        }
        if (StringUtils.isNotBlank(status)) {
            lambdaQueryWrapper.eq(UserEntity::getStatus, status);
        }
        IPage<UserEntity> page = this.page(
                new Query<UserEntity>().getPage(params),
                lambdaQueryWrapper
        );
        return new PageUtils<>(page);
    }

    @Override
    public UserDTO loadUserByUserName(String username) {
        Optional<UserEntity> userEntityOptional = Optional.ofNullable(this.getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getUsername, username)));
        return getUserDTO(userEntityOptional);
    }

    @Override
    public UserDTO loadUserByUserId(String userId) {
        Optional<UserEntity> userEntityOptional = Optional.ofNullable(getById(userId));
        return getUserDTO(userEntityOptional);
    }

    /**
     * 构造userDto
     *
     * @param userEntityOptional
     * @return
     */
    private UserDTO getUserDTO(Optional<UserEntity> userEntityOptional) {
        UserEntity userEntity = userEntityOptional.orElseThrow(() -> new UsernameNotFoundException("用户不存在"));
        UserDTO userDTO = new UserDTO();
        BeanUtil.copyProperties(userEntity, userDTO);
        List<UserRoleRelationEntity> userRoleRelationEntities = userRoleRelationDao.selectList(new LambdaQueryWrapper<UserRoleRelationEntity>().eq(UserRoleRelationEntity::getUserId, userEntity.getId()));
        List<String> roles = userRoleRelationEntities.stream()
                .map(UserRoleRelationEntity::getRoleId)
                .map(String::valueOf)
                .collect(Collectors.toList());
        userDTO.setRoles(roles);
        return userDTO;
    }

    @Override
    public R<String> register(@Validated UserEntity userEntity) {
        // 判断用户是否存在
        Optional<UserEntity> optionalUserEntity = this.lambdaQuery().eq(UserEntity::getUsername, userEntity.getUsername()).oneOpt();
        optionalUserEntity.ifPresent(user -> {
            log.error("用户已经存在{}", user.getUsername());
            throw new UsernameNotFoundException(user.getUsername());
        });
        userEntity.setPassword(BCrypt.hashpw(userEntity.getPassword()));
        boolean save = save(userEntity);
        return Rb.a(String.class).withSuccess(save).build();
    }


    @Override
    public UserVo getUserInfoByUsername(String username) {
        UserVo userVo = new UserVo();
        UserEntity userEntity = getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getUsername, username));
        BeanUtil.copyProperties(userEntity, userVo);
        return userVo;
    }

    @Override
    public UserRoleVo loadRoles(String userId) {
        UserRoleVo userRoleVo = new UserRoleVo();
        List<RoleEntity> list = roleService.list();
        List<RoleVo> roleVos = list.stream().map(roleEntity -> {
            RoleVo roleVo = new RoleVo();
            BeanUtils.copyProperties(roleEntity, roleVo);
            return roleVo;
        }).collect(Collectors.toList());
        userRoleVo.setAllRole(roleVos);
        List<Long> collect = userRoleRelationDao.selectList(new LambdaQueryWrapper<UserRoleRelationEntity>()
                .eq(UserRoleRelationEntity::getUserId, userId)).stream().map(UserRoleRelationEntity::getRoleId).collect(Collectors.toList());
        userRoleVo.setOwnRoles(collect);
        return userRoleVo;
    }
}
